import React, { ReactNode, useEffect } from "react";
import Draft, { Editor, EditorState, Modifier, RawDraftContentState, RichUtils, convertToRaw } from "draft-js";
import { UiButton } from "@/shared/Uikit";
import { useRef, useState } from 'react';
import { AtomicBlockUtils, ContentBlock } from 'draft-js';
import './TextEditor.css'
type TextEditorProps = {
  customComponents: {
    component: any,
    key: string,

    button: (insert: (props?: {
      [key: string]: unknown
    }) => void) => ReactNode
  }[],
  setValue: (value: RawDraftContentState) => void
  startValue?: RawDraftContentState
  readonly?: boolean
}


export default function TextEditor(props: TextEditorProps) {
  const [mounted, setMounted] = useState(false);
  const emptyContentState = Draft.convertFromRaw(props.startValue
    ? props.startValue
    : {
      entityMap: {},
      blocks: [],
    });
  const [editorState, setEditorState] = useState(() =>
    EditorState.createWithContent(emptyContentState)
  );

  const editor = useRef<Editor>(null);

  useEffect(() => {
    setMounted(true);
  }, [])

  useEffect(() => {
    props.setValue(convertToRaw(editorState.getCurrentContent()));
  }, [editorState.getCurrentContent()])


  function focusEditor() {
    editor.current?.focus();
  }

  const handleKeyCommand = (command: string) => {
    const newState = RichUtils.handleKeyCommand(editorState, command);

    if (newState) {
      setEditorState(newState);
      return 'handled';
    }

    return 'not-handled';
  }

  const blockRendererFn = (contentBlock: ContentBlock) => {
    const content = editorState.getCurrentContent();
    if (contentBlock.getType() === 'atomic') {
      const entityKey = contentBlock.getEntityAt(0);
      if (entityKey) {
        const entity = content.getEntity(entityKey);
        if (entity != null) {
          const entityType = entity.getType()
          const component = props.customComponents.find((component) => component.key == entityType)
          if (component != undefined) {
            return {
              component: component.component,
              editable: false,
              props: entity.getData()
            }
          }
        }
      }
    }
  }



  const customStyleMap = {
    "fontsize-large": {
      fontSize: 32,
    },
    "fontsize-small": {
      fontSize: 8,
    },

  };

  const customBlockStyleFn = (block: ContentBlock) => {
    switch (block.getType()) {
      case 'left':
        return 'align-left';
      case 'center':
        return 'align-center';
      case 'right':
        return 'align-right';
      default:
        return '';
    }
  }



  return (
    <>
      {!props.readonly &&
        <>
          <div>
            <UiButton 
            variant="secondary"
             onMouseDown={(e) => {
              e.preventDefault()
              setEditorState(RichUtils.toggleInlineStyle(editorState, "fontsize-large"));
            }}>
              <div className='h-[20px] w-[20px]'>
                T
              </div>
            </UiButton>
            <UiButton variant="secondary"  onMouseDown={(e) => {
              e.preventDefault()
              setEditorState(RichUtils.toggleInlineStyle(editorState, "fontsize-small"));
            }}>
              <div className='h-[20px] w-[20px]'>
                т
              </div>
            </UiButton>
            <UiButton
              onMouseDown={(e) => {
                e.preventDefault()
                setEditorState(RichUtils.toggleBlockType(editorState, 'left'))
              }}
              variant='secondary'
            >
              <img
                src="/icons/align_left.svg"
                alt='left'
                width={'20px'}
                height={'20px'}
              />
            </UiButton>

            <UiButton
              onMouseDown={(e) => {
                e.preventDefault()
                setEditorState(RichUtils.toggleBlockType(editorState, 'center'))
              }}
              variant='secondary'
            >
              <img
                src="/icons/align_center.svg"
                alt='center'
                width={'20px'}
                height={'20px'}
              />
            </UiButton>
            <UiButton
              onMouseDown={(e) => {
                e.preventDefault()
                setEditorState(RichUtils.toggleBlockType(editorState, 'right'))
              }}
              variant='secondary'
            >
              <img
                src="/icons/align_right.svg"
                alt='right'
                width={'20px'}
                height={'20px'}
              />
            </UiButton>
            <UiButton
              onMouseDown={(e) => {
                e.preventDefault()
                setEditorState(RichUtils.toggleInlineStyle(editorState, 'BOLD'))
              }}
              variant='secondary'
            >
              <img
                src="/icons/bold.svg"
                alt='bold'
                width={'20px'}
                height={'20px'}
              />
            </UiButton>
            <UiButton
              onMouseDown={(e) => {
                e.preventDefault()
                setEditorState(RichUtils.toggleInlineStyle(editorState, 'ITALIC'))
              }}
              variant='secondary'
            >
              <img
                src="/icons/italic.svg"
                alt='italic'
                width={'20px'}
                height={'20px'}
              />
            </UiButton>
            <UiButton
              onMouseDown={(e) => {
                e.preventDefault()
                setEditorState(RichUtils.toggleInlineStyle(editorState, 'UNDERLINE'))
              }}
              variant='secondary'
            >
              <img
                src="/icons/underline.svg"
                alt='underline'
                width={'20px'}
                height={'20px'}
              />
            </UiButton>

            {
              props.customComponents.map((component) => {
                return (
                  <span key={component.key}>
                    {component.button((props) => {
                      setEditorState(
                        addNewBlockAt(editorState,
                          component.key,
                          props ? props : {}
                        )
                      )
                    })
                    }
                  </span>
                )
              })
            }
          </div>
          <div
            onClick={focusEditor}
            style={{ border: "1px solid black", minHeight: "6em", cursor: "text" }}
          >
            {mounted &&
              <Editor
                customStyleMap={customStyleMap}
                editorKey="editor"
                ref={editor}
                blockStyleFn={customBlockStyleFn}
                editorState={editorState}
                onChange={setEditorState}
                blockRendererFn={blockRendererFn}
                handleKeyCommand={handleKeyCommand}
                readOnly={props.readonly}
              />
            }
          </div>
        </>
      }
      {props.readonly &&
        <div
        >
          {mounted &&
            <Editor
              customStyleMap={customStyleMap}
              editorKey="editor"
              ref={editor}
              blockStyleFn={customBlockStyleFn}
              editorState={editorState}
              onChange={setEditorState}
              blockRendererFn={blockRendererFn}
              handleKeyCommand={handleKeyCommand}
              readOnly={props.readonly}
            />
          }
        </div>
      }
    </>
  );
}



const addNewBlockAt = (
  editorState: EditorState,
  newBlockType = 'unstyled',
  data = {}
) => {
  const contentState = editorState.getCurrentContent();

  const contentStateWithEntity = contentState.createEntity(newBlockType, 'IMMUTABLE', data);
  const entityKey = contentStateWithEntity.getLastCreatedEntityKey();

  const newEditorState = AtomicBlockUtils.insertAtomicBlock(
    editorState,
    entityKey,
    ' '
  );

  return EditorState.forceSelection(
    newEditorState,
    newEditorState.getCurrentContent().getSelectionAfter()
  );
}
